"""
任务服务
负责管理文档转换任务的创建、执行、监控和状态管理
"""

import os
import logging
from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta
from ..models.task import Task
from ..models.history import History
from ..utils.redis_utils import RedisUtils
from .websocket_service import WebSocketService

logger = logging.getLogger(__name__)

class TaskService:
    """任务服务类"""
    
    def __init__(self, app=None):
        self.app = app
        self.redis_utils = RedisUtils(app) if app else None
        self.websocket_service = WebSocketService(app) if app else None
    
    def create_task(self, user_id: str, filename: str, original_name: str,
                   output_format: str, template_id: Optional[str] = None,
                   options: Optional[Dict] = None) -> Dict[str, Any]:
        """
        创建新的转换任务
        
        Args:
            user_id: 用户ID
            filename: 文件名
            original_name: 原始文件名
            output_format: 输出格式
            template_id: 模板ID（可选）
            options: 转换选项（可选）
            
        Returns:
            任务创建结果
        """
        try:
            # 创建任务记录
            task_data = {
                'user_id': user_id,
                'filename': filename,
                'original_name': original_name,
                'output_format': output_format,
                'template_id': template_id,
                'options': options or {},
                'status': Task.STATUS_PENDING,
                'progress': 0,
                'created_at': datetime.utcnow(),
                'updated_at': datetime.utcnow()
            }
            
            task_id = Task.create(task_data)
            
            # 记录历史
            History.record_upload(user_id, task_id, original_name, os.path.getsize(
                self._get_upload_path(filename)
            ))
            
            # 缓存任务信息
            if self.redis_utils:
                self.redis_utils.cache_task_info(task_id, task_data)
            
            logger.info(f"任务创建成功: {task_id}")
            
            return {
                'success': True,
                'task_id': task_id,
                'status': Task.STATUS_PENDING
            }
            
        except Exception as e:
            logger.error(f"任务创建失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def start_task(self, task_id: str) -> Dict[str, Any]:
        """
        启动任务执行
        
        Args:
            task_id: 任务ID
            
        Returns:
            启动结果
        """
        try:
            # 更新任务状态
            Task.update_status(task_id, Task.STATUS_PROCESSING)
            
            # 发送WebSocket通知
            if self.websocket_service:
                self.websocket_service.send_task_update(task_id, {
                    'status': Task.STATUS_PROCESSING,
                    'progress': 0,
                    'message': '任务开始处理'
                })
            
            logger.info(f"任务启动: {task_id}")
            
            return {'success': True, 'status': Task.STATUS_PROCESSING}
            
        except Exception as e:
            logger.error(f"任务启动失败 {task_id}: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def update_progress(self, task_id: str, progress: int, message: str = '') -> bool:
        """
        更新任务进度
        
        Args:
            task_id: 任务ID
            progress: 进度百分比 (0-100)
            message: 进度消息
            
        Returns:
            更新是否成功
        """
        try:
            # 验证进度值
            progress = max(0, min(100, progress))
            
            # 更新数据库
            Task.update_progress(task_id, progress)
            
            # 更新缓存
            if self.redis_utils:
                self.redis_utils.update_task_progress(task_id, progress)
            
            # 发送WebSocket通知
            if self.websocket_service:
                self.websocket_service.send_task_update(task_id, {
                    'progress': progress,
                    'message': message,
                    'timestamp': datetime.utcnow().isoformat()
                })
            
            logger.debug(f"任务进度更新 {task_id}: {progress}% - {message}")
            
            return True
            
        except Exception as e:
            logger.error(f"进度更新失败 {task_id}: {str(e)}")
            return False
    
    def complete_task(self, task_id: str, output_file: str, file_size: int) -> Dict[str, Any]:
        """
        完成任务
        
        Args:
            task_id: 任务ID
            output_file: 输出文件路径
            file_size: 文件大小
            
        Returns:
            完成结果
        """
        try:
            # 获取任务信息
            task = Task.find_by_id(task_id)
            if not task:
                raise ValueError(f"任务不存在: {task_id}")
            
            # 更新任务状态
            completion_data = {
                'output_file': output_file,
                'file_size': file_size,
                'completed_at': datetime.utcnow()
            }
            
            Task.update_completion(task_id, completion_data)
            
            # 记录转换历史
            History.record_conversion(
                task['user_id'],
                task_id,
                task['output_format'],
                file_size,
                True
            )
            
            # 清理缓存
            if self.redis_utils:
                self.redis_utils.clear_task_cache(task_id)
            
            # 发送完成通知
            if self.websocket_service:
                self.websocket_service.send_task_update(task_id, {
                    'status': Task.STATUS_COMPLETED,
                    'progress': 100,
                    'message': '转换完成',
                    'output_file': os.path.basename(output_file),
                    'file_size': file_size,
                    'download_url': f'/api/download/{task_id}'
                })
            
            logger.info(f"任务完成: {task_id}")
            
            return {
                'success': True,
                'status': Task.STATUS_COMPLETED,
                'output_file': output_file,
                'file_size': file_size
            }
            
        except Exception as e:
            logger.error(f"任务完成处理失败 {task_id}: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def fail_task(self, task_id: str, error_message: str, error_type: str = 'unknown') -> Dict[str, Any]:
        """
        标记任务失败
        
        Args:
            task_id: 任务ID
            error_message: 错误消息
            error_type: 错误类型
            
        Returns:
            处理结果
        """
        try:
            # 获取任务信息
            task = Task.find_by_id(task_id)
            if not task:
                raise ValueError(f"任务不存在: {task_id}")
            
            # 更新任务状态
            failure_data = {
                'error_message': error_message,
                'error_type': error_type,
                'failed_at': datetime.utcnow()
            }
            
            Task.update_failure(task_id, failure_data)
            
            # 记录失败历史
            History.record_conversion(
                task['user_id'],
                task_id,
                task['output_format'],
                0,
                False,
                error_message
            )
            
            # 清理缓存
            if self.redis_utils:
                self.redis_utils.clear_task_cache(task_id)
            
            # 发送失败通知
            if self.websocket_service:
                self.websocket_service.send_task_update(task_id, {
                    'status': Task.STATUS_FAILED,
                    'progress': 0,
                    'message': f'转换失败: {error_message}',
                    'error': error_message,
                    'error_type': error_type
                })
            
            logger.error(f"任务失败: {task_id} - {error_message}")
            
            return {
                'success': True,
                'status': Task.STATUS_FAILED,
                'error': error_message
            }
            
        except Exception as e:
            logger.error(f"任务失败处理失败 {task_id}: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def cancel_task(self, task_id: str, user_id: str) -> Dict[str, Any]:
        """
        取消任务
        
        Args:
            task_id: 任务ID
            user_id: 用户ID
            
        Returns:
            取消结果
        """
        try:
            # 验证任务所有权
            task = Task.find_by_id(task_id)
            if not task:
                return {'success': False, 'error': '任务不存在'}
            
            if task['user_id'] != user_id:
                return {'success': False, 'error': '无权限取消此任务'}
            
            # 检查任务状态
            if task['status'] in [Task.STATUS_COMPLETED, Task.STATUS_FAILED, Task.STATUS_CANCELLED]:
                return {'success': False, 'error': '任务已完成，无法取消'}
            
            # 更新任务状态
            Task.update_status(task_id, Task.STATUS_CANCELLED)
            
            # 清理缓存
            if self.redis_utils:
                self.redis_utils.clear_task_cache(task_id)
            
            # 发送取消通知
            if self.websocket_service:
                self.websocket_service.send_task_update(task_id, {
                    'status': Task.STATUS_CANCELLED,
                    'message': '任务已取消'
                })
            
            logger.info(f"任务取消: {task_id}")
            
            return {'success': True, 'status': Task.STATUS_CANCELLED}
            
        except Exception as e:
            logger.error(f"任务取消失败 {task_id}: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def get_task_status(self, task_id: str, user_id: str) -> Dict[str, Any]:
        """
        获取任务状态
        
        Args:
            task_id: 任务ID
            user_id: 用户ID
            
        Returns:
            任务状态信息
        """
        try:
            # 先尝试从缓存获取
            if self.redis_utils:
                cached_info = self.redis_utils.get_task_info(task_id)
                if cached_info and cached_info.get('user_id') == user_id:
                    return {'success': True, 'task': cached_info}
            
            # 从数据库获取
            task = Task.find_by_id(task_id)
            if not task:
                return {'success': False, 'error': '任务不存在'}
            
            if task['user_id'] != user_id:
                return {'success': False, 'error': '无权限查看此任务'}
            
            return {'success': True, 'task': task}
            
        except Exception as e:
            logger.error(f"获取任务状态失败 {task_id}: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def get_user_tasks(self, user_id: str, status: Optional[str] = None,
                      limit: int = 50, offset: int = 0) -> Dict[str, Any]:
        """
        获取用户任务列表
        
        Args:
            user_id: 用户ID
            status: 任务状态过滤（可选）
            limit: 返回数量限制
            offset: 偏移量
            
        Returns:
            任务列表
        """
        try:
            tasks = Task.find_by_user(user_id, status, limit, offset)
            total = Task.count_by_user(user_id, status)
            
            return {
                'success': True,
                'tasks': tasks,
                'total': total,
                'limit': limit,
                'offset': offset
            }
            
        except Exception as e:
            logger.error(f"获取用户任务失败 {user_id}: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def get_task_statistics(self, user_id: Optional[str] = None) -> Dict[str, Any]:
        """
        获取任务统计信息
        
        Args:
            user_id: 用户ID（可选，为空则获取全局统计）
            
        Returns:
            统计信息
        """
        try:
            if user_id:
                stats = Task.get_user_statistics(user_id)
            else:
                stats = Task.get_global_statistics()
            
            return {'success': True, 'statistics': stats}
            
        except Exception as e:
            logger.error(f"获取任务统计失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def cleanup_expired_tasks(self, days: int = 30) -> Dict[str, Any]:
        """
        清理过期任务
        
        Args:
            days: 保留天数
            
        Returns:
            清理结果
        """
        try:
            cutoff_date = datetime.utcnow() - timedelta(days=days)
            
            # 获取过期任务
            expired_tasks = Task.find_expired_tasks(cutoff_date)
            
            cleaned_count = 0
            for task in expired_tasks:
                try:
                    # 删除输出文件
                    if task.get('output_file') and os.path.exists(task['output_file']):
                        os.remove(task['output_file'])
                    
                    # 删除任务记录
                    Task.delete_by_id(task['_id'])
                    cleaned_count += 1
                    
                except Exception as e:
                    logger.warning(f"清理任务失败 {task['_id']}: {str(e)}")
            
            logger.info(f"清理过期任务完成: {cleaned_count} 个")
            
            return {
                'success': True,
                'cleaned_count': cleaned_count,
                'total_found': len(expired_tasks)
            }
            
        except Exception as e:
            logger.error(f"清理过期任务失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def _get_upload_path(self, filename: str) -> str:
        """获取上传文件路径"""
        upload_dir = self.app.config.get('UPLOAD_FOLDER', 'storage/uploads') if self.app else 'storage/uploads'
        return os.path.join(upload_dir, filename)
    
    def retry_failed_task(self, task_id: str, user_id: str) -> Dict[str, Any]:
        """
        重试失败的任务
        
        Args:
            task_id: 任务ID
            user_id: 用户ID
            
        Returns:
            重试结果
        """
        try:
            # 验证任务
            task = Task.find_by_id(task_id)
            if not task:
                return {'success': False, 'error': '任务不存在'}
            
            if task['user_id'] != user_id:
                return {'success': False, 'error': '无权限重试此任务'}
            
            if task['status'] != Task.STATUS_FAILED:
                return {'success': False, 'error': '只能重试失败的任务'}
            
            # 重置任务状态
            Task.update_status(task_id, Task.STATUS_PENDING)
            Task.update_progress(task_id, 0)
            
            # 清理错误信息
            Task.update_by_id(task_id, {
                'error_message': None,
                'error_type': None,
                'failed_at': None,
                'retry_count': task.get('retry_count', 0) + 1,
                'updated_at': datetime.utcnow()
            })
            
            logger.info(f"任务重试: {task_id}")
            
            return {'success': True, 'status': Task.STATUS_PENDING}
            
        except Exception as e:
            logger.error(f"任务重试失败 {task_id}: {str(e)}")
            return {'success': False, 'error': str(e)}